dbt×Snowflakeでのロール構成の土台を考えてみた #dbt #SnowflakeDB
さがらです。
早速ですがSnowflakeでデータマートを構築する上で、dbtはとても相性の良いツールです。(この2つの製品を併せる良さをまとめたこちらの記事もぜひご覧ください。)
しかし、実際にdbtとSnowflakeを併せて使おうとすると「どんなロール構成にすれば良いんだ…?」と悩む方は多いと思います。
そこで、dbtを使用するにあたってのSnowflakeロール構成の土台を考えてみましたので、本記事でまとめてみます。
結論:私の考えるdbtにおけるSnowflakeロール構成の土台
以下の図が、私が考えるdbt×Snowflakeでのロール構成の土台です。
各ロールの役割
dbt_admin_role
- dbt projectと紐づく全てのデータベースを管理するロール。
sysadmin
だとdbtと関係のないデータベースまで触れてしまうため、sysadmin
の下にdbtで作られたデータベースを管理するためのロールがあった方が良いと考えました。
dbt_aaa_dev_role
- dbt project「aaa」のジョブを実行してデータマートを生成するロール。dbt project作成時にoptionで紐付けるロール。
- dbt projectに設定したデータベース内での
CREATE SCHEMA
権限をもたせることで、ユーザーごとの開発用スキーマと本番環境用のスキーマを構築できるようにし、それぞれのスキーマに対してテーブルやビューの生成が可能となります。
dbt_aaa_select_role
- dbt project「aaa」で作られたデータマートを参照するロール。
- 参照できるスキーマを本番環境用のスキーマだけにすることで、dbtでの開発中のスキーマを見せずに済みます。
dbt_aaa_dev_role
の子ロールにすることで、共通するUSAGE
権限やSELECT
権限を多重管理せずに済みます。
- 以下、別プロジェクトを作成するたびに
dbt_bbb_dev_role
、dbt_bbb_select_role
、といった命名規則でロールを作成していく。
※このロール構成での必要なprivilegeの詳細は、本記事末尾のクエリサンプルをご覧ください。
この構成での懸念点
複数のdbt projectで作られたデータベースのテーブル同士をJOINしたいユーザーもいるのではないか?
dbt projectは基本的に1つのデータベースと一対のため、複数のdbt projectから生成された別データベースのテーブル同士をJOINしてSELECTしたいユーザー向けのロールが必要になる場面も出てくると思います。
対策としては、大きく3つあると考えています。
- セカンダリロールを使う
- 複数のdbt projectで作られたデータベースをSELECTで参照できるロール、それぞれを子に持つ別のロールを作る
- dbt projectの数が増えるごとにロールが増えるリスクもあるため注意が必要ですが、セカンダリロールが使えない状況の場合にはこの方法を取るのが良いと思います。
- あるdbt projectにて、別のdbt projectで生成されたテーブルとJOINしたmodelを新しく定義する
- 個人的にこの方法はNGと考えています。
- 理由としては、dbtで開発することでデータリネージが自動で構築されて元のテーブルまで遡ることが出来るのに、別projectで生成されたテーブルを引用すると元テーブルが1つのproject内で追えなくなってしまい、dbtを使っているメリットが損なわれるためです。
参考:本記事のロール構成を作るクエリサンプル
- 元データを持つデータベース:
aaa_db
- dbtの開発用データベース:
dbt_aaa_db
- dbtで作られた本番用データが置かれるスキーマ:
production
- この記事の「本番環境へ適用させるための設定変更」に沿って、スキーマ名を変更する必要があります。
-- 必要なロールの作成 use role securityadmin; create role dbt_admin_role; create role dbt_aaa_dev_role; create role dbt_aaa_select_role; -- 作成したロールをsysadminからのツリー構造にする grant role dbt_admin_role to role sysadmin; grant role dbt_aaa_dev_role to role dbt_admin_role; grant role dbt_aaa_select_role to role dbt_aaa_dev_role; -- dbtでのジョブ実行用のウェアハウスを作成 use role sysadmin; create or replace warehouse dbt_wh with warehouse_size = 'XSMALL' warehouse_type = 'STANDARD' auto_suspend = 60 auto_resume = true min_cluster_count = 1 max_cluster_count = 1 scaling_policy = 'STANDARD' initially_suspended = TRUE; grant usage on warehouse dbt_wh to role dbt_aaa_dev_role; -- dbtで作られたデータマートに対してクエリを発行して分析するためのウェアハウスを作成 ※任意。既存の分析用ウェアハウスでもOK use role sysadmin; create or replace warehouse analysys_wh with warehouse_size = 'XSMALL' warehouse_type = 'STANDARD' auto_suspend = 60 auto_resume = true min_cluster_count = 1 max_cluster_count = 1 scaling_policy = 'STANDARD' initially_suspended = TRUE; grant usage on warehouse analysys_wh to role dbt_aaa_select_role; -- 必要なデータベースの定義 use role sysadmin; create or replace database aaa_db clone citibike; -- dbtが参照する元データを持つデータベース。サンプルなのでcloneを使って新しく作成しています create database dbt_aaa_db; -- dbtでの開発用スキーマ、本番用スキーマが置かれる、「dbtの開発・本番環境」にあたるデータベース -- dbtの開発・本番環境にあたるデータベースは、dbt_admin_roleが管理できるように所有権を移動させる use role sysadmin; grant ownership on database dbt_aaa_db to role dbt_admin_role; -- dbtの開発・本番環境にあたるデータベースに対してdbt上で開発が出来るように、必要な権限をdbtでの開発用ロールに付与 use role dbt_admin_role; grant create schema on database dbt_aaa_db to role dbt_aaa_dev_role; grant usage on database dbt_aaa_db to role dbt_aaa_select_role; -- dbtの開発・本番環境にあたるデータベースに対して、本番用のスキーマを事前に作成しておく(SELECT権限を事前に付与するため) use role dbt_aaa_dev_role; create schema production; -- dbtで作られたテーブルが格納される本番用スキーマに対して、SELECTを行うロールが参照できるようにUSAGE権限を付与 use role dbt_aaa_dev_role; grant usage on schema dbt_aaa_db.production to role dbt_aaa_select_role; -- dbtで作られたテーブルが格納される本番用スキーマに対して、SELECTを行うロールが本番用のスキーマで今後作られるテーブル・ビューをすべてをSELECTできるようにする use role securityadmin; grant select on future tables in schema dbt_aaa_db.production to role dbt_aaa_select_role; grant select on future views in schema dbt_aaa_db.production to role dbt_aaa_select_role; -- dbtが参照する元データを持つデータベースとスキーマへのUSAGE権限、全てのテーブルへのSELECT権限を付与。今後新しく作られるスキーマとテーブルにも対応させる use role sysadmin; grant usage on database aaa_db to role dbt_aaa_dev_role; grant usage on schema aaa_db.public to role dbt_aaa_dev_role; grant select on all tables in schema aaa_db.public to role dbt_aaa_dev_role; use role securityadmin; grant usage on future schemas in database aaa_db to role dbt_aaa_dev_role; grant select on future tables in schema aaa_db.public to role dbt_aaa_dev_role; grant select on future views in schema aaa_db.public to role dbt_aaa_dev_role;